import gtk
import gtk.glade
import pango
import pickle
import logging
import sys
import os
from sugar.datastore import datastore
from sugar.activity import activity

from book import Book
from book import Bookshelf

class iabv:
    ''' The class describes a iabv object, 
    which is the main graphical user interface '''

    current_font_size = 14 # used by zoom_in and zoom_out

    # The current line, used by next_page and prev_page,
    # this is the last visible line of text, determined by 
    # get_number_of_visible_lines
    current_line = 0

    def help(self, *args):
        ''' Help '''
        pass

    def load(self):
        ''' load a book, book reader toolbar button handler '''
        pass

    def prev_page(self, *args):
        ''' prev page book, reader toolbar button handler '''
        iter = self.text_buffer.get_iter_at_line(self.current_line -\
                self.get_number_of_visible_lines())
        self.text_view.scroll_to_iter(iter, 0)

        # increase the current_line
        self.current_line -= self.get_number_of_visible_lines()

    def next_page(self, *args):
        '''  next page book, reader toolbar button handler '''
        iter = self.text_buffer.get_iter_at_line(self.current_line +\
                self.get_number_of_visible_lines())
        self.text_view.scroll_to_iter(iter, 0)

        # increase the current_line
        self.current_line += self.get_number_of_visible_lines()

    def zoom_in(self, *args):
        ''' increase TextView font '''
        self.current_font_size += 2
        self.text_view.modify_font(pango.FontDescription('sans \
            bold '+str(self.current_font_size)))

        # update the current_line (which depends on the font size)
        self.current_line = self.get_number_of_visible_lines()

    def zoom_out(self, *args):
        ''' decrease TxtView font '''
        self.current_font_size -= 2
        self.text_view.modify_font(pango.FontDescription('sans \
            bold '+str(self.current_font_size)))

        # update the current_line (which depends on the font size)
        self.current_line = self.get_number_of_visible_lines()

    hpaned_visible = 1
    def hidepaned(self, *args):
        ''' Hides the VBox on the left of the HPaned... '''
        if self.hpaned_visible:
            self.hpaned.set_position(0)
            self.hpaned_visible = 0
        else:
            self.hpaned.set_position(200)
            self.hpaned_visible = 1

    def get_number_of_visible_lines(self):
        ''' Returns the number of visible lines for the self.current_font_size '''
        font_desc = pango.FontDescription("Mono bold "+str(self.current_font_size))
        layout = self.text_view.create_pango_layout('')
        layout.set_font_description(font_desc)
        text_width, text_height = layout.get_pixel_size()
        rect = self.text_view.get_visible_rect()
        return rect.height/text_height

        # TODO: Need to clean after...

    def search_for_book(self, *args):
        ''' left (left from the hpaned) button handler '''
        # Create new Book object here ...
        self.current_book = Book(self.entry_left_down.get_text(), self.progressbar)

        # Show it in the textView
        self.text_buffer.set_text(self.current_book.get_book(self.current_book))

        # Update the current_line when loading a book
        self.current_line = self.get_number_of_visible_lines()

        # progress
        self.progressbar.set_fraction(1)

        # Add it (temporary) to the treeView
        # TODO: check if it exists already!!!
        self.list_store.append([self.current_book.book_id])

    def quit(self):
        self.save_bookshelf()
        gtk.main_quit()

    def save_bookshelf(self, *args):
        print "saving bookshelf"
        # the bookshelf file is named iabv.bookshelf
        filename = 'iabv.bookshelf'
        # create a datastore object
        dsobject = datastore.create()
        # metadata for the datastore object
        dsobject.metadata['title'] = filename
        # the picke module serializes objects in simple txt (?!)
        dsobject.metadata['mime_type'] = 'text/plain'

        # write the actual file to the data directory of this activity's root. 
        file_path = os.path.join(activity.get_activity_root(), 'instance', filename)
        f = open(file_path, 'w')
        try:
            pickle.dump(self.current_bookshelf, f)
        finally:
            f.close()

        # set the file_path in the datastore.
        dsobject.set_file_path(file_path)

        datastore.write(dsobject)

        # return the dsobject, not used for the moment...
        return dsobject

    def load_bookshelf(self):
        ds_objects, num_objects = datastore.find({'title':'iabv.bookshelf'})
        # debug, show all the objects... 
        # this is only used for testing, there should be only one file
        # containing the bookshelf
        print '------------------------- results ---------------------------'
        print "Number of Objects: " + str(num_objects)
        for i in xrange (0, num_objects, 1):
            print "File Path: " + ds_objects[i].get_file_path()
            print "Title: " + ds_objects[i].metadata['title']

        # get the first one (still testing)
        try:
            filehandler = open(ds_objects[0].get_file_path(), 'r')
            object = pickle.load(filehandler)

            # remove the file, a new one will be created on exit, there must be
            # only one...
            ds_objects[0].destroy()
            datastore.delete(ds_objects[0].object_id)

        except IndexError:
        # there is no bookshelf file...
        # creating new bookshelf
            object = Bookshelf()

        # return the bookshelf
        return object
    
    def save_in_bookshelf(self, current_book):
        ''' saves the current book in the bookshelf '''
        pass

    def remove_from_bookshelf(self, current_book):
        ''' remove a book from the bookshelf '''
        # TODO: not finished
        pass
    
    def __init__(self, runaslib=True):
        # Load the bookshelf
        self.current_bookshelf = self.load_bookshelf()

        # Load the glade XML file
        self.xml = gtk.glade.XML("/home/qaz/Activities/iabv.activity/iabv.glade")

        # Get the main window
        self.main_window = self.xml.get_widget("window")
        # Get windows child
        self.w_child = self.main_window.get_child()
        self.widget = self.w_child
        # Close handler
        self.main_window.connect("delete_event", self.quit) 

        # Get the textview
        self.text_view = self.xml.get_widget("textview")
        self.text_buffer = self.text_view.get_buffer()
        # Default font - Mono, 14, bold, for now...
        self.text_view.modify_font(pango.FontDescription('mono bold 14'))

        # Get and set up the treeview
        self.tree_view =  self.xml.get_widget("treeview")
        # one row for the moment (string) ...
        self.list_store = gtk.ListStore(str)
        # attatch the model to the treeView
        self.tree_view.set_model(self.list_store)
        # only text ...
        self.text_renderer = gtk.CellRendererText()
        # title, gtk.CellRendererText(), text=columnId
        self.col = gtk.TreeViewColumn("Recently viewed Books",
                self.text_renderer, text = 0)
        #self.col.pack_start(self.cell, True)
        self.tree_view.append_column(self.col)
        # Need to add handlers for the treeView ...

        # Get the horizontal pane
        self.hpaned =  self.xml.get_widget("hpaned")

        # Get the entry on the left
        self.entry_left_down = self.xml.get_widget("entryLeftDown")

        # Get the button on the left
        self.button_left_down = self.xml.get_widget("buttonLeftDown")
        # Connect the button handler here ...
        self.button_left_down.connect("clicked", self.search_for_book)

        # Get the little progress bar on the left
        self.progressbar = self.xml.get_widget("progressbar")

        #
        # Get the bookshelf window
        self.bookshelf_window = self.xml.get_widget("window_bookshelf")
        
if __name__ == '__main__':
    iabv(False)
